import scale from './scale.js'
import store from '../../store'
import debounce from './debounce.js'

/**
 * 初始化蓝牙设备
 */
function init(success, fail) {
    uni.openBluetoothAdapter({
        success: e => {
            //console.log('初始化蓝牙成功:' + e.errMsg);
            // 获取本机蓝牙适配器状态
            getBluetoothAdapterState(success, fail);
        },
        fail: e => {
            //console.log('初始化蓝牙失败，错误码：' + (e.errCode || e.errMsg));
            if (e.errCode !== 0) {
                fail && fail(e.errCode, e.errMsg)
                initTypes(e.errCode, e.errMsg);
            }
        }
    });
}


/**
 * 获取本机蓝牙适配器状态
 */
function getBluetoothAdapterState(success, fail) {
    uni.getBluetoothAdapterState({
        success: res => {
            //console.log('获取本机蓝牙适配器状态成功--' + JSON.stringify(res));
            success && success(res)
        },
        fail: e => {
            //console.log('获取本机蓝牙适配器状态失败，错误码：' + e.errCode);
            if (e.errCode !== 0) {
                fail && fail(e.errCode, e.errMsg)
                initTypes(e.errCode);
            }
        }
    });
}

/**
 * 初始化蓝牙设备
 */
function openBluetoothAdapter() {
    uni.openBluetoothAdapter({
        success: e => {
            //console.log('初始化蓝牙成功:' + e.errMsg);
            // 获取本机蓝牙适配器状态
            getBluetoothAdapterState();
        },
        fail: e => {
            //console.log(e)
            //console.log('初始化蓝牙失败，错误码：' + (e.errCode || e.errMsg));
            if (e.errCode !== 0) {
                initTypes(e.errCode, e.errMsg);
            }
        }
    });
}

/**
 * 开始搜索蓝牙设备
 */
function startBluetoothDevicesDiscovery(success, fail) {
    uni.startBluetoothDevicesDiscovery({
        success: e => {
            // //console.log('开始搜索蓝牙设备:' + e.errMsg);
            onBluetoothDeviceFound(success, fail);
        },
        fail: e => {
            //console.log('搜索蓝牙设备失败，错误码：' + e.errCode);
            if (e.errCode !== 0) {
                fail && fail(e.errCode)
                initTypes(e.errCode);
            }
        },

    });

}

/**
 * 发现外围设备
 */
function onBluetoothDeviceFound(success, fail) {
    uni.onBluetoothDeviceFound(devices => {
        // //console.log('开始监听寻找到新设备的事件', devices);
        success && success(devices)
        // getBluetoothDevices(success, fail);
    });

}

/**
 * 获取在蓝牙模块生效期间所有已发现的蓝牙设备。包括已经和本机处于连接状态的设备。
 */
function getBluetoothDevices(success, fail) {
    uni.getBluetoothDevices({
        success: res => {
            //console.log('获取蓝牙设备成功:' + res.errMsg);
            success && success(res.devices)
        },
        fail: e => {
            //console.log('获取蓝牙设备错误，错误码：' + e.errCode);
            if (e.errCode !== 0) {
                fail && fail(e.errCode)
                initTypes(e.errCode);
            }
        }
    });
}

/**
 * 停止搜索蓝牙设备
 */
function stopBluetoothDevicesDiscovery(types) {
    return new Promise((result, reject) => {
        uni.stopBluetoothDevicesDiscovery({
            success: e => {
                //console.log('停止搜索蓝牙设备:' + e.errMsg);
                result(e.errMsg)
            },
            fail: e => {
                //console.log('停止搜索蓝牙设备失败，错误码：' + e.errCode);
                if (e.errCode !== 0) {
                    initTypes(e.errCode);
                    reject(e.errCode)
                }
            }
        });
    })

}

/**
 * 断开与低功耗蓝牙设备的连接
 */
function closeBLEConnection(deviceId) {
    uni.closeBLEConnection({
        deviceId,
        success: res => {
            //console.log(res);
        },
        fail: e => {
            //console.log('断开低功耗蓝牙成功，错误码：' + e.errCode);
            if (e.errCode !== 0) {
                initTypes(e.errCode);
            }
        }
    });
}

/**
 *    断开蓝牙模块
 */
function closeBluetoothAdapter() {
    uni.closeBluetoothAdapter({
        success: res => {
            //console.log('断开蓝牙模块成功');
        }
    });
}

/**
 * 引导用户打开APP权限设置界面
 */
function openAppPage() {
    plus.nativeUI.confirm("APP蓝牙权限没有开启，是否去开启？", function (e) {
        if (e.index == 0) {
            if (uni.getSystemInfoSync().platform == 'android') {
                var Intent = plus.android.importClass("android.content.Intent");
                var Settings = plus.android.importClass("android.provider.Settings");
                var Uri = plus.android.importClass("android.net.Uri");
                var mainActivity = plus.android.runtimeMainActivity();
                var intent = new Intent();
                intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
                var uri = Uri.fromParts("package", mainActivity.getPackageName(), null);
                intent.setData(uri);
                mainActivity.startActivity(intent);
            } else if (uni.getSystemInfoSync().platform == 'ios') {
                var UIApplication = plus.ios.import("UIApplication");
                var application2 = UIApplication.sharedApplication();
                var NSURL2 = plus.ios.import("NSURL");
                var setting2 = NSURL2.URLWithString("app-settings:");
                application2.openURL(setting2);
                plus.ios.deleteObject(setting2);
                plus.ios.deleteObject(NSURL2);
                plus.ios.deleteObject(application2);
            }
        } else {
            uni.navigateBack({
                delta: 1
            });
        }
    }, {
        "buttons": ["Yes", "No"],
        "verticalAlign": "center"
    });
}

/**
 * 引导用户打开相应权限界面
 */
function openPermissionPage() {
    if (uni.getSystemInfoSync().platform == 'android') {
        plus.nativeUI.confirm("手机蓝牙没有开启，是否去开启？", function (e) {
            if (e.index == 0) {
                var main = plus.android.runtimeMainActivity(); //获取activity
                var Intent = plus.android.importClass('android.content.Intent');
                var Settings = plus.android.importClass('android.provider.Settings');
                var intent = new Intent(Settings.ACTION_BLUETOOTH_SETTINGS);
                main.startActivity(intent);
            } else {
                uni.navigateBack({
                    delta: 1
                });
            }
        }, {
            "buttons": ["Yes", "No"],
            "verticalAlign": "center"
        });
    } else if (uni.getSystemInfoSync().platform == 'ios') {
        toast('检测蓝牙未开启，请手动开启蓝牙');
    }
}

function openPermissionPageWEIXIN() {
    uni.showModal({
        title: '提示',
        content: '蓝牙权限未开启，请手动去开启',
        showCancel: false,
        confirmText: '知道了',
        success: res => {
        },
        fail: () => {
        },
        complete: () => {
        }
    });
}

/**
 * 监听低功耗蓝牙连接状态的改变事件。包括开发者主动连接或断开连接，设备丢失，连接异常断开等等
 */
function onBLEConnectionStateChange() {
    uni.onBLEConnectionStateChange(res => {
        // 该方法回调中可以用于处理连接意外断开等异常情况
        //console.log(`蓝牙连接状态 -------------------------->`);
        //console.log(JSON.stringify(res));
        if (!res.connected) {
            const SystemInfoSync = uni.getSystemInfoSync();
            if (SystemInfoSync.platform == 'android') {
                // uni.showModal({
                // 	title: '提示',
                // 	content: '蓝牙已断开',
                // 	showCancel: false,
                // 	success: function(res) {
                // 		if (res.confirm) {
                // 			uni.navigateBack({
                // 				delta: 2
                // 			});
                // 		}
                // 	}
                // });
            }
        }
    });
}

/**
 * 5.连接低功耗蓝牙
 */
async function createBLEConnection(success, fail) {
    uni.createBLEConnection({
        deviceId: store.getters.Bluetooth.activeBle.deviceId,
        success: async res => {
            //注意这里需要延迟下获取服务，否则获取服务可能为空
            await new Promise((resolve) => setTimeout(resolve, 1000))
            //6.获取可写服务
            await getBLEDeviceServices(success, fail)
        },
        fail: e => {
            //console.log('连接低功耗蓝牙失败，错误码：' + e.errCode);
            fail && fail(e.errCode)
            // if (e.errCode !== 0) {
            // 	initTypes(e.errCode);
            // }
        }
    });
}

/**
 *7. 获取当前蓝牙所有服务
 */
async function getBLEDeviceServices(success, fail) {
    uni.getBLEDeviceServices({
        deviceId: store.getters.Bluetooth.activeBle.deviceId,
        success: async res => {
            // //console.log('获取到蓝牙服务为',res.services);
            let activeBle = {
                ...store.getters.Bluetooth.activeBle,
                services: res.services,
                serviceId: '',
                write: {
                    serviceId: '',
                    characteristicId: '',
                },
                read: { //特征值支持 notify 或者 indicate
                    serviceId: '',
                    characteristicId: '',
                },
                notify: { //特征值支持 notify 或者 indicate
                    serviceId: '',
                    characteristicId: '',
                }
            }
            store.commit('set_BlueToothActiveBle', activeBle)
            if (store.getters.Bluetooth.activeBle.services <= 0) { //获取蓝牙可写服务失败，请重新获取
                //循环获取服务
                debounce(() => {
                    getBLEDeviceServices(success, fail)
                }, 500)
            } else {
                //循环获取服务下的可写特征值
                for (let i = 0; i < store.getters.Bluetooth.activeBle.services.length; i++) {
                    //获取服务的特征
                    await getBLEDeviceCharacteristics(i)
                }
                success && success(store.getters.Bluetooth.activeBle)
            }
        },
        fail: e => {
            //console.log('获取设备服务失败，错误码：' + e.errCode);
            fail && fail(e.errCode)
            if (e.errCode !== 0) {
                initTypes(e.errCode);
            }
        }
    });
}

/**
 * 获取某个服务下的所有特征值
 */
function getBLEDeviceCharacteristics(index) {
    return new Promise((result, reject) => {
        uni.getBLEDeviceCharacteristics({
            deviceId: store.getters.Bluetooth.activeBle.deviceId,
            serviceId: store.getters.Bluetooth.activeBle.services[index].uuid,
            success: res => {
                //console.log('获取特征值成功:' + store.getters.Bluetooth.activeBle.deviceId + 'serviceId' + store.getters.Bluetooth.activeBle.services[index].uuid + JSON.stringify( res));
                let activeBle = {
                    ...store.getters.Bluetooth.activeBle,
                    characteristics: res.characteristics
                }
                // that.Bluetooth.activeBle.characteristics = res.characteristics;
                if (activeBle.characteristics.length <= 0) {
                    //console.log('获取特征值失败，请重试!');
                    return;
                } else {

                    //循环获取服务下的可写特征值
                    for (let i = 0; i < activeBle.characteristics.length; i++) {
                        if (activeBle.characteristics[i].properties.write) {
                            activeBle.write.characteristicId = activeBle.characteristics[i].uuid
                            activeBle.write.serviceId = activeBle.services[index].uuid
                        }
                        if (activeBle.characteristics[i].properties.read) {
                            activeBle.read.characteristicId = activeBle.characteristics[i].uuid
                            activeBle.read.serviceId = activeBle.services[index].uuid
                        }
                        //启用低功耗蓝牙设备特征值变化时的 notify 功能，订阅特征值。注意：必须设备的特征值支持 notify 或者 indicate 才可以成功调用
                        if (activeBle.characteristics[i].properties.notify) {
                            activeBle.notify.characteristicId = activeBle.characteristics[i].uuid
                            activeBle.notify.serviceId = activeBle.services[index].uuid
                        }
                    }
                    result(activeBle)
                }
                store.commit('set_BlueToothActiveBle', activeBle)
                // that.set_BlueToothActiveBle(activeBle)
            },
            fail: e => {
                //console.log('获取特征值失败，错误码：' + e.errCode);
                if (e.errCode !== 0) {
                    initTypes(e.errCode);
                }
            }
        });
    })
}

//8. 启用低功耗蓝牙设备特征值变化时的 notify 功能，订阅特征值。
function notifyBLECharacteristicValueChange(success, fail) {
    uni.notifyBLECharacteristicValueChange({
        state: true, // 启用 notify 功能
        deviceId: store.getters.Bluetooth.activeBle.deviceId, //蓝牙设备 id
        serviceId: store.getters.Bluetooth.activeBle.notify.serviceId, //蓝牙特征值对应服务的 uuid
        characteristicId: store.getters.Bluetooth.activeBle.notify.characteristicId, //蓝牙特征值的 uuid
        success(res) {
            //console.log('启用低功耗蓝牙设备特征值变化时的 notify 功能，订阅特征值', res.errMsg)
            success && success(res.errMsg)
        },
        fail(e) {
            //console.log('特征值变化失败', e);
            fail && fail()
            if (e.errCode !== 0) {
                // initTypes(e.errCode);
            }
        }
    })
}

let Str = '', starArr = ['31008001', '31000301', '31008201', '31000101', '31000201', '31000a01']

function initParams() {
    Str = ''
}

function readBLECharacteristicValue() {
    //console.log('activeBle', store.getters.Bluetooth.activeBle);
    // let num = 1,
    // 	len = 0,
    // 	cmd = 0,
    // 	allLen = 0,
    // 	Str = ''
    // 13 0001 01 00000002 7b7d
    // onBLECharacteristicValueChange必须先启用 notifyBLECharacteristicValueChange 接口才能接收到设备推送的 notification。
    uni.onBLECharacteristicValueChange(async function (characteristic) {
        // //arrbuff转成16进制字符串
        let Strin16 = scale.ab2hex(characteristic.value)
        //console.log(Strin16);
        //处理华为手机丢包问题，根据前缀判断当前包如果不完整就丢弃当前的数据，继续接收下一次的数据
        starArr.forEach(item => {
            if (Strin16.includes(item)) {
                Str = ''
            }
        })
        Str += Strin16;
        await ProcessingData();
    })
    uni.readBLECharacteristicValue({
        deviceId: store.getters.Bluetooth.activeBle.deviceId, //蓝牙设备 id
        serviceId: store.getters.Bluetooth.activeBle.read.serviceId, //蓝牙特征值对应服务的 uuid
        characteristicId: store.getters.Bluetooth.activeBle.write.characteristicId, //蓝牙特征值的 uuid
        success(res) {
            //console.log('readBLECharacteristicValue:', res.errCode)
        }
    })
}

//处理接受到的数据
async function ProcessingData() {
    //拿到body的长度 在把16进制转成10进制
    let len = parseInt(Str.slice(8, 16), 16)
    let cmd = parseInt(Str.slice(2, 6), 16)
    //计算16进制字符串的总长度
    let allLen = (len + 8) * 2
    // //console.log('   total:'+allLen +'  cmd:'+cmd+'  str:' + Str.length);
    if (Str.length > allLen || Str.length == allLen) {
        //获取符合长度的数据
        let endStr = Str.slice(0, allLen)

        //留下多余的数据继续拼接
        Str = Str.slice(allLen)
        let jsonstr = endStr.slice(16, endStr.length)
        //16进制转字符串
        let string = await scale.hexCharCodeToStr(jsonstr)
        let req = {
            cmd,
            len,
            data: JSON.parse(string)
        }
        uni.$emit('onBLECharacteristicValueChange', req)
        //判断这次接收到的次数和
        Incomplete(string)
    }
}

//接收到数据不完整时处理提示
let userCount = 0

function Incomplete(string) {
    try {
        let params = JSON.parse(string) || ''
        let method = JSON.parse(params.payload).method || ''
        let {count, audit} = JSON.parse(params.payload).params
        let parms = JSON.parse(params.payload).parms || ''
        //其他指令发送成功后重置参数
        if (!method) {
            userCount = 0
        } else if (audit == 0) {//非审计
            userCount++
            if (method == 'thing.event.punch.post') {//盖章事件
                if (userCount != count) {//申请单推送和临时盖章的丢次错误处理
                    let req = {
                        userCount,
                        count
                    }
                    uni.$emit('BLEuserCountError', req)
                    userCount = count
                }
            } else {
                userCount = 0
            }
        }

    } catch (e) {
        //TODO handle the exception
    }
}

function initUserCount(num) {
    userCount = num
}

//向低功耗蓝牙设备特征值中写入二进制数据
function writeBLECharacteristicValue(hex) {
    return new Promise((result, reject) => {
        //16进制字符转byte数组
        const arrayBuffer = scale.hex2auffer(hex)
        uni.writeBLECharacteristicValue({
            // 这里的 deviceId 需要在 getBluetoothDevices 或 onBluetoothDeviceFound 接口中获取
            deviceId: store.getters.Bluetooth.activeBle.deviceId, //蓝牙设备 id
            // 这里的 serviceId 需要在 getBLEDeviceServices 接口中获取
            serviceId: store.getters.Bluetooth.activeBle.write.serviceId, //蓝牙特征值对应服务的 uuid
            // 这里的 characteristicId 需要在 getBLEDeviceCharacteristics 接口中获取
            characteristicId: store.getters.Bluetooth.activeBle.write.characteristicId, //蓝牙特征值的 uuid
            // 这里的value是ArrayBuffer类型
            value: arrayBuffer,
            success(res) {
                result(res.errMsg)
            },
            fail(err) {
                //console.log(err);
                result(err)
            }
        })
    })
}

//向低功耗蓝牙设备特征值中写入二进制数据
function writeBLECharacteristicValueBuffer(arrayBuffer) {
    return new Promise((result, reject) => {
        //16进制字符转byte数组
        // const arrayBuffer = scale.str2ab(hex)
        // const arrayBuffer = scale.textToArrayBuffer(hex)
        uni.writeBLECharacteristicValue({
            // 这里的 deviceId 需要在 getBluetoothDevices 或 onBluetoothDeviceFound 接口中获取
            deviceId: store.getters.Bluetooth.activeBle.deviceId, //蓝牙设备 id
            // 这里的 serviceId 需要在 getBLEDeviceServices 接口中获取
            serviceId: store.getters.Bluetooth.activeBle.write.serviceId, //蓝牙特征值对应服务的 uuid
            // 这里的 characteristicId 需要在 getBLEDeviceCharacteristics 接口中获取
            characteristicId: store.getters.Bluetooth.activeBle.write.characteristicId, //蓝牙特征值的 uuid
            // 这里的value是ArrayBuffer类型
            value: arrayBuffer,
            success(res) {
                result(res.errMsg)
            },
            fail(err) {
                //console.log(err);
                result(err)
            }
        })
    })
}

/**
 * 判断初始化蓝牙状态
 */
function initTypes(code, errMsg) {
    switch (code) {
        case 10000:
            //console.log('未初始化蓝牙适配器');
            // openAppPage()
            break;
        case 10001:
            //console.log('未检测到蓝牙，请打开蓝牙重试！');
            //#ifdef MP-WEIXIN
            openPermissionPageWEIXIN()
            //#endif
            //#ifdef APP-PLUS
            openPermissionPage()
            //#endif
            break;
        case 10002:
            //console.log('没有找到指定设备');
            // toast('没有找到指定设备');
            break;
        case 10003:
            //console.log('连接失败');
            // toast('连接失败');
            break;
        case 10004:
            //console.log('没有找到指定服务');
            // toast('没有找到指定服务');
            break;
        case 10005:
            //console.log('没有找到指定特征值');
            // toast('没有找到指定特征值');
            break;
        case 10006:
            //console.log('当前连接已断开');
            // toast('当前连接已断开');
            break;
        case 10007:
            toast('当前特征值不支持此操作');
            break;
        case 10008:
            toast('其余所有系统上报的异常');
            break;
        case 10009:
            toast('Android 系统特有，系统版本低于 4.3 不支持 BLE');
            break;
        default:
            toast(errMsg);
    }
}

/**
 * 弹出框封装
 */
function toast(content, showCancel = false) {
    uni.showModal({
        title: '提示',
        content,
        showCancel
    });
}

/**
 * 发送蓝牙指令
 * start|in
 * in|命令号
 * end|in|包数
 * @param{Object} obj
 * @param{string} obj.data 数据
 * @param{string} obj.type 类型or(申请单)、in（指令）
 */
async function sendBluetoothCmd({data, type}) {
    let body_16 =  typeof data === 'string' ? data : JSON.stringify(data)
    let start = [`start|${type}`]
    let arr = splitCmd(body_16, type)
    let end = [`end|${type}|${arr.length}`]
    let newArr = [...start, ...arr, ...end]
    //console.log('newArr', newArr)
    try{
        //多个指令串行发送，并行可能会失败
        await writeCmd(newArr, 0)
        return {success: true}
    }catch (err) {
        console.error(err)
        return {success: false, msg: err.message}
    }
}

// 分割指令每20位分割一下，返回数组
function splitCmd(hex, type) {
    //console.log('hex', hex)
    let arr = []
    for (let a = 0; a < Math.ceil(hex.length / 8); a++) {
        //6f727c代表16进制的or|
        let str = `${type}|` + hex.slice(a * 8, a * 8 + 8)
        arr.push(str)
    }
    return arr
}

//arr为hex分割的数组，i为当前数组下标
async function writeCmd(arr, i) {
    //console.log(`arr${i}=${arr[i]}`)
    let byte = scale.textToArrayBuffer(arr[i])
    //字符串转16进制
    let res = await writeBLECharacteristicValueBuffer(byte)
    if (res === 'writeBLECharacteristicValue:ok') {
        i++
        if (i > arr.length - 1) {
            return
        }
        await new Promise((resolve) => setTimeout(resolve, 200))
        await writeCmd(arr, i)
    } else {
        throw Error('系统繁忙')
    }
}


export default {
    initParams,//初始化参数
    init, //初始化蓝牙
    startBluetoothDevicesDiscovery, //搜索蓝牙设备
    stopBluetoothDevicesDiscovery, //停止搜索蓝牙
    getBluetoothDevices, // 已发现的设备
    closeBLEConnection, //断开蓝牙
    closeBluetoothAdapter, //断开蓝牙模块
    onBLEConnectionStateChange, //监听蓝牙断开
    writeBLECharacteristicValue, //写入数据
    createBLEConnection, //连接指定特征蓝牙
    notifyBLECharacteristicValueChange, //启用低功耗蓝牙设备特征值变化时的 notify 功能，订阅特征值
    readBLECharacteristicValue,//监听蓝牙回复
    initUserCount,
    sendBluetoothCmd, // 发送蓝牙指令
}
